using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace IUPUI.StellarResults.Client.UIElements
{
	/// <summary>
	/// A view of multiple <see cref="ObservatoryView"/>s.
	/// </summary>
	public partial class ObservatoriesViewerControl : UserControl, ISimulationViewTabControl
	{
		#region Private Properties
		private bool m_IsInitialized = false;
		private Simulation m_Simulation;
		private ININ.Collections.SerializableDictionary<string, ObservatoryView> m_ObservatoryViews =
			new ININ.Collections.SerializableDictionary<string, ObservatoryView>();
		private DateTime m_CurrentDateTimeUTC;
		#endregion Private Properties

		#region Public Properties
		/// <summary>
		/// Gets a value indicating whether this instance is initialized.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is initialized; otherwise, <c>false</c>.
		/// </value>
		public bool IsInitialized
		{
			get
			{
				return m_IsInitialized;
			}
		}

		/// <summary>
		/// Gets or sets the simulation.
		/// </summary>
		/// <value>The simulation.</value>
		[Browsable(false)]
		public Simulation Simulation
		{
			get
			{
				return m_Simulation;
			}
			set
			{
				if (m_Simulation != value)
				{
					m_Simulation = value;
					OnSimulationChanged();
				}
			}
		}

		/// <summary>
		/// Gets or sets the current date time.
		/// </summary>
		/// <value>The current date time.</value>
		public DateTime CurrentDateTimeUTC
		{
			get
			{
				return m_CurrentDateTimeUTC;
			}
			set
			{
				if (m_CurrentDateTimeUTC != value)
				{
					m_CurrentDateTimeUTC = value;
					OnCurrentDateTimeChanged();
				}
			}
		}
		#endregion Public Properties

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="ObservatoriesViewerControl"/> class.
		/// </summary>
		public ObservatoriesViewerControl()
		{
			InitializeComponent();
			m_IsInitialized = true;

			OnSimulationChanged();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ObservatoriesViewerControl"/> class.
		/// </summary>
		/// <param name="container">The container.</param>
		public ObservatoriesViewerControl(
			IContainer container)
			: this()
		{
			container.Add(this);
		}
		#endregion Constructors

		/// <summary>
		/// Handles the Modified event of the m_Observatories control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void m_Observatories_Modified(object sender, EventArgs e)
		{
			OnSimulationChanged();
		}

		/// <summary>
		/// Called when [current date time changed].
		/// </summary>
		protected virtual void OnCurrentDateTimeChanged()
		{
			// Set the current datetime on all observatory views
			foreach (ObservatoryView view in m_ObservatoryViews.Values)
			{
				view.CurrentDateTimeUTC = m_CurrentDateTimeUTC;
			}
		}

		/// <summary>
		/// Called when [simmulation changed].
		/// </summary>
		protected virtual void OnSimulationChanged()
		{
			if (m_IsInitialized && m_Simulation != null)
			{
				m_Simulation.Observatories.Modified +=
					new EventHandler(m_Observatories_Modified);

				// Setup LayoutPanel
				this.m_LayoutPanel.Controls.Clear();
				this.m_LayoutPanel.SuspendLayout();
				this.m_LayoutPanel.ColumnStyles.Clear();
				this.m_LayoutPanel.ColumnCount = 
					(m_Simulation.Observatories.Count > 1) ? 2 : 1;
				this.m_LayoutPanel.RowStyles.Clear();
				this.m_LayoutPanel.RowCount = (int)Math.Ceiling(
					(decimal)m_Simulation.Observatories.Count / 2);

				for (int i = 0; i < this.m_LayoutPanel.ColumnCount; i++)
				{
					if (m_LayoutPanel.RowCount > 2)
					{
						// Subtract 10 pixels here to handle the scroll bar
						this.m_LayoutPanel.ColumnStyles.Add(
							new System.Windows.Forms.ColumnStyle(
							System.Windows.Forms.SizeType.Absolute,
							m_LayoutPanel.Width / 2 - 10));
					}
					else
					{
						this.m_LayoutPanel.ColumnStyles.Add(
							new System.Windows.Forms.ColumnStyle(
								System.Windows.Forms.SizeType.Percent,
								(100 / this.m_LayoutPanel.ColumnCount)));
					}
				}
				
				for (int i = 0; i < this.m_LayoutPanel.RowCount; i++)
				{
					if (m_LayoutPanel.RowCount > 2)
					{
						this.m_LayoutPanel.RowStyles.Add(
							new System.Windows.Forms.RowStyle(
								System.Windows.Forms.SizeType.Absolute,
								m_LayoutPanel.Height/2));
					}
					else
					{
						this.m_LayoutPanel.RowStyles.Add(
							new System.Windows.Forms.RowStyle(
								System.Windows.Forms.SizeType.Percent,
								50));
					}
				}
				this.m_LayoutPanel.ResumeLayout(true);

				ObservatoryView observatoryView;
				int column = 0;
				int row = 0;

				m_ObservatoryViews.Clear();
				foreach (Observatory observatory in m_Simulation.Observatories)
				{
					if (!m_ObservatoryViews.ContainsKey(observatory.ID))
					{
						observatoryView = new ObservatoryView(this.components);
						observatoryView.Simulation = m_Simulation;
						observatoryView.Observatory = observatory;
						observatoryView.CurrentDateTimeUTC = m_CurrentDateTimeUTC;
						observatoryView.BorderStyle = BorderStyle.FixedSingle;
						observatoryView.Dock = DockStyle.Fill;

						m_ObservatoryViews.Add(
							observatory.ID,
							observatoryView);

						this.m_LayoutPanel.Controls.Add(observatoryView, column, row);

						// Set column and row for next iteration
						column = (column == 0) ? 1 : 0;
						if (column == 0)
						{
							row++;
						}
					}
				}
			}
			else
			{
				this.m_LayoutPanel.Controls.Clear();
			}
		}

		/// <summary>
		/// Handles the Resize event of the m_LayoutPanel control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void m_LayoutPanel_Resize(object sender, EventArgs e)
		{
			// If there are more than 2 rows, then we need to handle resizing ourselves
			if (m_LayoutPanel.RowCount > 2)
			{
				foreach (RowStyle style in m_LayoutPanel.RowStyles)
				{
					style.SizeType = SizeType.Absolute;
					style.Height = m_LayoutPanel.Height / 2;
				}
				foreach (ColumnStyle style in m_LayoutPanel.ColumnStyles)
				{
					// Subtract 10 pixels here to handle the scroll bar
					style.SizeType = SizeType.Absolute;
					style.Width = m_LayoutPanel.Width / 2 - 10;
				}
			}
		}
	}
}
